package com.ruoyi.web.controller.an;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.an.domain.AnMechanism;
import com.ruoyi.an.domain.AnMechanismMember;
import com.ruoyi.an.domain.AnWechatUser;
import com.ruoyi.an.domain.AnWechatUserMechanism;
import com.ruoyi.an.service.IAnMechanismMemberService;
import com.ruoyi.an.service.IAnMechanismService;
import com.ruoyi.an.service.IAnWechatUserService;
import com.ruoyi.an.util.AnPlatformUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.controller.common.CommonUtils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.List;
import java.util.UUID;

import static com.ruoyi.common.config.WeixinConfig.appid;
import static com.ruoyi.common.config.WeixinConfig.secret;


@Controller
@RequestMapping("/WeixinController")
public class WeixinController {
    @Autowired
    private IAnWechatUserService anWechatUserService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private IAnMechanismService anMechanismService;
    @Autowired
    private IAnMechanismMemberService anMechanismMemberService;

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    @PostMapping(value = "/wxRedirect")
    public @ResponseBody
    String wxRedirect(@RequestBody JSONObject requestObj, HttpServletRequest request) {
        boolean isFirstLogin = false;
        if (requestObj.containsKey("encryptedData") && requestObj.containsKey("iv")) {
            if (requestObj.getString("encryptedData").length() + requestObj.getString("iv").length() > 0) {
                isFirstLogin = true;
            }
        }
        String encryptedData = requestObj.containsKey("encryptedData") ? requestObj.getString("encryptedData") : "";
        if (encryptedData.contains("%")) {
            encryptedData = URLDecoder.decode(encryptedData, StandardCharsets.UTF_8);
        }

        String iv = requestObj.containsKey("iv") ? requestObj.getString("iv") : "";
        String nickName = requestObj.containsKey("nickName") ? requestObj.getString("nickName") : "";
        String userIcon = requestObj.containsKey("userIcon") ? requestObj.getString("userIcon") : "";
        nickName = nickName.replace("'", "");
        String code = requestObj.getString("code");
        String promotionCode = requestObj.containsKey("promotionCode") ? requestObj.getString("promotionCode") : "";
        String errmsg = "";
        JSONObject object = new JSONObject();
        AnWechatUser resultWechatUser = null;
        try {
            String access_token = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code");
            errmsg = access_token;
            JSONObject access = JSONObject.parseObject(access_token);
            if (StringUtils.isNotEmpty(access.getString("openid")) && isFirstLogin) {
                //解密
                String phoneNumber = getWxMiniPhone(access.getString("session_key"), iv, encryptedData);
                // 生成令牌
                AnWechatUser wechatUser = anWechatUserService.selectAnWechatUserByOpenId(access.getString("openid"));
                if (wechatUser == null) {
                    AnWechatUser addUser = new AnWechatUser();
                    addUser.setNickName(nickName);
                    addUser.setUserIcon(userIcon);
                    addUser.setOpenId(access.getString("openid"));
                    addUser.setPhone(phoneNumber);
                    addUser.setCreateTime(DateUtils.getNowDate());
                    addUser.setIsMechanism(1L);
                    addUser.setIpAddress(CommonUtils.getIpAddress(request));
                    if (StringUtils.isNotEmpty(promotionCode))
                    {
                        addUser.setPromotionCode(promotionCode);
                        fillWebUserMechanism(addUser);
                    }
                    anWechatUserService.insertAnWechatUser(addUser);
                    resultWechatUser = addUser;
                } else {
                    resultWechatUser = wechatUser;
                }
            }
            object.put("code", 200);
            object.put("msg", "成功登录");
            //登录后信息存到缓存
            if (StringUtils.isNotEmpty(access.getString("openid"))) {
                resultWechatUser = anWechatUserService.selectAnWechatUserByOpenId(access.getString("openid"));
            }
            if (resultWechatUser != null) {
                UUID uuid = UUID.randomUUID();
                String token = uuid.toString();
                redisTemplate.opsForValue().set("user:" + token, JSON.toJSONString(resultWechatUser));
                object.put("token", token);
            } else {
                object.put("code", -1);
                object.put("msg", "登录失败");
                object.put("errInfo", access);
            }
            return object.toString();
        } catch (Exception e) {
            e.printStackTrace();
            object.put("code", -1);
            object.put("msg", "登录失败");
            object.put("errInfo", errmsg);
            return object.toJSONString();
        }
    }


    @RequestMapping(value = "/wxjump", method = RequestMethod.GET)
    public String index() {
        //后缀为.html的文件名
        return "wxjump";
    }

    /**
     * 填充用户的机构信息
     * @param tokenWechatUser
     */
    public void fillWebUserMechanism(AnWechatUser tokenWechatUser)
    {
        AnMechanismMember anMechanismMember = new AnMechanismMember();
        anMechanismMember.setPromotionCode(tokenWechatUser.getPromotionCode());
        //设置机构名称
        List<AnMechanismMember> anMechanismMembers = anMechanismMemberService.selectAnMechanismMemberList(anMechanismMember);
        if (anMechanismMembers.size() == 0) {
            return;
        }
        for (AnMechanismMember mechanismMember : anMechanismMembers) {
            AnMechanism anMechanism = anMechanismService.selectAnMechanismByMechanismId(mechanismMember.getMechanismId());
            tokenWechatUser.setScreeningSource(anMechanism.getMechanismName() + "-" + mechanismMember.getMemberName());
            tokenWechatUser.setMechanismId(mechanismMember.getMechanismId());
            tokenWechatUser.setMechanismMemberId(mechanismMember.getMechanismMemberId());
        }
    }


    public static String getWxMiniPhone(String sessionkey, String iv, String encryptedData) throws Exception {
        byte[] encrypData = Base64Utils.decodeFromString(encryptedData);
        byte[] ivData = Base64Utils.decodeFromString(iv);
        byte[] sessionKey = Base64Utils.decodeFromString(sessionkey);
        String resultString = null;
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
        SecretKeySpec keySpec = new SecretKeySpec(sessionKey, "AES");
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            resultString = new String(cipher.doFinal(encrypData), "UTF-8");
        } catch (Exception e) {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            resultString = new String(cipher.doFinal(encrypData), "UTF-8");
        }
        JSONObject object = JSONObject.parseObject(resultString);
        // 拿到手机号码
        String phone = object.getString("phoneNumber");
        return phone;
    }



}
